package com.corona.lwjgl3;

import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
import com.badlogic.gdx.utils.SharedLibraryLoader;
import com.corona.Game;
import com.corona.utils.CommonUtils;
import com.corona.utils.LogUtils;
import org.lwjgl.system.Configuration;
import oshi.SystemInfo;
import oshi.hardware.HardwareAbstractionLayer;

import java.io.File;

import static com.corona.constants.Constants.*;

/**
 * 启动器
 *
 * @author Corona
 * @since 2024-12-22
 */
public class Lwjgl3Launcher {
    public static void main(String[] args) {
        //这段代码看起来是用于检查是否需要启动一个新的 Java 虚拟机（JVM），如果需要，则执行相应的操作并退出当前代码的执行。
        //具体来说，StartupHelper.startNewJvmIfRequired() 是一个方法调用，它可能根据某些条件决定是否启动一个新的 JVM
        if (StartupHelper.startNewJvmIfRequired()) {
            return;
        }
        // 允许 macOS 无需特殊标志运行
        allowMacOsToRunWithoutFlag();
        // 检查用户主目录是否在临时文件夹中
        // 这段代码的主要目的是检查当前项目的根目录是否位于某些特定的临时文件夹中，
        // 例如 macOS 的 /private 文件夹或 Windows 的 C:\Windows\System32 文件夹。
        // 如果检测到当前项目的根目录在这些临时文件夹中，它会警告用户，因为这些文件夹通常不适合保存游戏数据，可能会导致保存文件丢失或无法保存的问题。
        checkForUserHomeInTempFolder();
        // 获取显示屏缩放比例
        int scale = getScale();
        createApplication(scale, args);
    }

    // 允许 macOS 无需特殊标志运行
    // 在macOS上，LWJGL3 项目需要额外执行一个步骤：在运行配置中，将 VM 选项设置为-XstartOnFirstThread。
    // 或者，将以下实验性代码片段添加到您的main()方法中：有关此内容的其他信息可在此处
    // if (SharedLibraryLoader.isMac) Configuration.GLFW_LIBRARY_NAME.set("glfw_async");找到。
    private static void allowMacOsToRunWithoutFlag() {
        // 如果当前操作系统是 macOS
        if (SharedLibraryLoader.isMac) {
            // 设置 GLFW 库的名称为 "glfw_async"
            // GLFW：这是一个用于创建窗口、处理用户输入和管理OpenGL上下文的库，常用于游戏和图形应用程序开发。
            Configuration.GLFW_LIBRARY_NAME.set(GLFW_ASYNC);
        }
    }

    // 检查用户主目录是否在临时文件夹中
    private static void checkForUserHomeInTempFolder() {
        // 获取当前项目的根目录绝对路径
        String savePath = new File("").getAbsoluteFile().getAbsolutePath().toLowerCase();
        // 打印根目录路径
        LogUtils.systemLog(SYSTEM_CHECK_LOG, SYSTEM_CHECK_SAVE_PATH + savePath);
        // 检查路径是否以 "/private" 或 "c:\\windows\\system32" 开头
        if (savePath.startsWith(WARN_TO_SAVE_PATH_FOR_MAC) || savePath.startsWith(WARN_TO_SAVE_PATH_FOR_WINDOWS)) {
            // 如果路径不合适，警告用户
            LogUtils.systemLog(SYSTEM_CHECK_LOG, SYSTEM_CHECK_SAVE_PATH + "unSafe");
        }
    }

    // 获取显示屏缩放比例
    private static int getScale() {
        int height = Lwjgl3ApplicationConfiguration.getDisplayMode().height;
        if (height <= 800) {
            return 2;
        }
        if (height > 1080) {
            return 6;
        }
        return 3;
    }

    private static void createApplication(int scale, String[] args) {
        new Lwjgl3Application(new Game(), getDefaultConfiguration(scale, args));
    }

    private static Lwjgl3ApplicationConfiguration getDefaultConfiguration(int scale, String[] args) {
        Lwjgl3ApplicationConfiguration configuration = new Lwjgl3ApplicationConfiguration();
        // 设置窗口的分辨率
        configuration.setWindowedMode(scale * WINDOW_BASE_WIDTH, scale * WINDOW_BASE_HEIGHT);
        // 设置窗口的标题
        configuration.setTitle(WINDOW_TITLE);
        // 设置窗口的图标
        configuration.setWindowIcon(WINDOW_ICON_256, WINDOW_ICON_64, WINDOW_ICON_32);
        // 设置前台 FPS
        configuration.setForegroundFPS(DEFAULT_FPS);
        // 这种方法通常用于确保游戏的帧率稍微高于显示器的最大刷新率，以避免帧率限制。
        // config.setForegroundFPS(Lwjgl3ApplicationConfiguration.getDisplayMode().refreshRate + 1);
        // 开启垂直同步
        configuration.useVsync(true);
        // 打印系统信息
        printSystemInfo();
        // 处理命令行参数并配置 LibGDX
        if (CommonUtils.isContainCommand(args, USE_ANGLE)) {
            configuration.setOpenGLEmulation(Lwjgl3ApplicationConfiguration.GLEmulation.ANGLE_GLES20, 0, 0);
        }
        return configuration;
    }

    // 打印系统信息
    private static void printSystemInfo() {
        // 创建一个系统信息对象
        SystemInfo systemInfo = new SystemInfo();
        // 获取硬件抽象层对象
        HardwareAbstractionLayer hardware = systemInfo.getHardware();
        // 获取操作系统家族
        String os = System.getProperty("os.name");
        // 获取处理器的微架构
        String arch = hardware.getProcessor().getProcessorIdentifier().getMicroarchitecture();
        // 打印操作系统家族
        LogUtils.systemLog(SYSTEM_INFO, "os = " + os);
        // 打印计算机型号
        LogUtils.systemLog(SYSTEM_INFO, "model = " + hardware.getComputerSystem().getModel());
        // 打印处理器微架构
        LogUtils.systemLog(SYSTEM_INFO, "arch = " + arch);
    }
}
